package com.titanrise.crm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.titanrise.crm.common.constants.WaitForStatusConstant;
import com.titanrise.crm.common.enums.LogEffect;
import com.titanrise.crm.common.enums.TradeStatusEnum;
import com.titanrise.crm.common.utils.*;
import com.titanrise.crm.dao.CustomerDao;
import com.titanrise.crm.domain.model.*;
import com.titanrise.crm.domain.model.enums.BelongStatus;
import com.titanrise.crm.domain.vo.UserVo;
import com.titanrise.crm.environment.annotation.Autowired;
import com.titanrise.crm.environment.annotation.Service;
import com.titanrise.crm.environment.menu.MenuContext;
import com.titanrise.crm.environment.menu.action.Action;
import com.titanrise.crm.exception.*;
import com.titanrise.crm.handler.CustomerServicePrinter;
import com.titanrise.crm.service.CustomerService;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLSyntaxErrorException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;

/**
 * @Description:
 * @Author: pront
 * @Time:2024-11-25 21:16
 */
@Service
public class CustomerServiceImpl implements CustomerService {
    @Override
    public Action findById(MenuContext menuContext) {
        System.out.println("请输入你要查询的商品id：");
        String pid = IOUtil.inputLine();

        Optional.ofNullable(customerDao.selectByIdProduct(pid)).ifPresent(CustomerServicePrinter::printByIdProduct);

        return Action.JUMP_TO_MENU("/customer/product");

    }
    @Autowired
    private CustomerDao customerDao;


    private final Function<String, Either<String, String>> checker = IOUtil.getGenericChecker();
    private final Function<String, Either<String, String>> nonChecker = Functions.flow(
            ValidationUtil::trimThenRight
    );

    private Map<Integer, Messages> msgMap = new HashMap<>();

    @Override
    public Action showAllProducts() {
        try {
            Thread waitThread = IOUtil.waitForSelective(WaitForStatusConstant.SELECT);
            Optional.ofNullable(customerDao.showAllProducts()).ifPresent(CustomerServicePrinter::printAllProducts);
            waitThread.interrupt();
            Thread.sleep(150);
        } catch (InterruptedException e) {
            Console.println(e.getMessage(), LogEffect.RED, LogEffect.BOLD);
        }
        return Action.JUMP_TO_MENU("/customer/product");
    }

    @Override
    public Action manageUserInfo(MenuContext menuContext) throws InterruptedException {
        Thread waitThread = IOUtil.waitForSelective(WaitForStatusConstant.SELECT);
        Role currentRole = (Role) menuContext.getState().get("CurrentRole");
        UserVo userVo = new UserVo();
        Optional.ofNullable(currentRole.getUid()).ifPresent(uid -> {
            User user = customerDao.selectUserById(uid);
            Role role = customerDao.selectRoleByUid(uid);
            BeanUtil.copyProperties(user, userVo);
            BeanUtil.copyProperties(role, userVo);
        });
        waitThread.interrupt();
        Thread.sleep(150);
        CustomerServicePrinter.printUserInfo(userVo);
        return Action.JUMP_TO_MENU("/customer/user");
    }

    @Override
    public Action sendMsg2Salesperson(MenuContext menuContext) throws InterruptedException {
        try {
            Role currentRole = (Role) menuContext.getState().get("CurrentRole");
            if (currentRole.getIsBelong() == BelongStatus.FALSE) throw new NonRelativeSalespersonException();

            String salesId = customerDao.selectSalesIdByClientId(currentRole.getUid());
            CustomerServicePrinter.printRelativeSalesperson(salesId);
            String content = ProjectUtil.getLine("请输入消息内容，输入e退出：", checker);
            if("e".equals(content)) return Action.JUMP_TO_MENU("/customer");
            Thread waitThread = IOUtil.waitForSelective(WaitForStatusConstant.SEND);
            Messages message = Messages.builder().messageId(ProjectUtil.generateUUID())
                    .content(content)
                    .receiverId(salesId)
                    .senderId(currentRole.getUid()).build();
            int count = customerDao.sendMessage(message);
            if (count != 1) throw new SystemErrorException();
            waitThread.interrupt();
            Thread.sleep(150);
        } catch (SystemErrorException | NonRelativeSalespersonException e) {
            Console.println(e.getMessage() + "!", LogEffect.RED, LogEffect.BOLD);
            sendMsg2Salesperson(menuContext);
        }
        Thread.sleep(150);
        return Action.JUMP_TO_MENU("/customer");
    }

    @Override
    public Action msgBox(MenuContext menuContext) {
        msgMap.clear();
        Role currentRole = (Role) menuContext.getState().get("CurrentRole");
        String uid = Optional.ofNullable(currentRole.getUid()).orElseGet(() -> "");
        List<Messages> list = customerDao.selectAllMsgByReceiverId(uid);
        if(list == null || list.size() == 0){
            Console.println("暂无消息!", LogEffect.YELLOW, LogEffect.BOLD);
            return Action.JUMP_TO_MENU("/customer");
        }
        CustomerServicePrinter.printAllMsg(list);
        list.forEach(msg -> {
            msgMap.put(msgMap.size() + 1, msg);
        });
        return Action.JUMP_TO_MENU("/customer/manageMsgBox");
    }

    @Override
    public Action readMessage(MenuContext menuContext) {
        try {
            int no = IOUtil.getIntegerNo("请输入序号");
            Messages msg = msgMap.get(no);
            if (!ObjectUtil.isNull(msg)) {
                Console.println(msg.getContent(), LogEffect.WHITE);
                int count = customerDao.updateReadedMes(msg.getMessageId(), LocalDateTime.now());
                if (count != 1) throw new SystemErrorException();
            }
        } catch (InputFormatException | SystemErrorException e) {
            Console.println(e.getMessage(), LogEffect.RED, LogEffect.BOLD);
            readMessage((menuContext));
        }
        while (true) {
            String isExit = ProjectUtil.getLine("输入e退出", checker);
            if (isExit.equals("e")) return Action.JUMP_TO_MENU("/customer/manageMsgBox");
        }
    }


    @Override
    public Action deleteMessage() {
        try {
            Thread waitThread = IOUtil.waitForSelective(WaitForStatusConstant.DELETE);
            int no = IOUtil.getIntegerNo("请输入序号");
            Messages msg = msgMap.get(no);
            if (!ObjectUtil.isNull(msg)) {
                int count = customerDao.deleteMsgById(msg.getMessageId());
                if (count != 1) throw new SystemErrorException();
            }
            waitThread.interrupt();
            Thread.sleep(150);
        } catch (InputFormatException | SystemErrorException | InterruptedException e) {
            Console.println(e.getMessage(), LogEffect.RED, LogEffect.BOLD);
            deleteMessage();
        }
        return Action.JUMP_TO_MENU("/customer/manageMsgBox");
    }

    @Override
    public Action buy(MenuContext menuContext) {
        Connection conn = null;
        try {
            Role currentRole = (Role) menuContext.getState().get("CurrentRole");
            String salesId = customerDao.selectSalesIdByClientId(currentRole.getUid());
            if (ObjectUtil.isNull(salesId)) throw new NotFindRelativeSalesException();

            conn = ProjectUtil.getConnection();
            String productId = ProjectUtil.getLine("请输入产品编号,输入e退出：", checker);
            if("e".equals(productId)) return Action.JUMP_TO_MENU("/customer");
            Product product = customerDao.selectProductByProductId(productId);
            if (ObjectUtil.isEmpty(product)) throw new NotFindInfoException();
            int stock = product.getStock();
            int count = IOUtil.getIntegerNo("请输入购买数量: ");
            if (count > stock) throw new NotEnoughStockException();
            Thread waitThread = IOUtil.waitForSelective(WaitForStatusConstant.RESULT);
//            更新商品库存
            int updateCount = customerDao.updateProductStock(productId, stock - count);
//            发送消息通知销售
            Messages message = Messages.builder()
                    .messageId(ProjectUtil.generateUUID())
                    .senderId(currentRole.getUid())
                    .receiverId(salesId)
                    .content(currentRole.getName() + "购买了" + count + "个" + product.getSkuName() + "产品。请尽快处理！")
                    .build();
            int sendCount = customerDao.sendMessage(message);
//            建立交易信息
            String tradeId = customerDao.exitTradeCount(currentRole.getUid(), salesId, product.getSkuName());
            int tradeCount;
            BigDecimal totalPrice = product.getSkuPrice().multiply(new BigDecimal(count));
            if (ObjectUtil.isNotNull(tradeId)) {
//                销售创建了潜在交易的情况下
                tradeCount = customerDao.updateTradeStatusById(tradeId, TradeStatusEnum.PAID.getStatus(), currentRole.getName(), totalPrice);
            } else {
                Trade trade = Trade.builder().tradeId(ProjectUtil.generateUUID())
                        .clientId(currentRole.getUid())
                        .salespersonId(salesId)
                        .goodsName(product.getSkuName())
                        .number(count)
                        .price(totalPrice)
                        .status(TradeStatusEnum.CONFIRM_DEAL.getStatus())
                        .build();
                tradeCount = customerDao.insertTradeCount(trade);
            }
            if (sendCount != 1 || updateCount != 1 || tradeCount != 1) throw new SQLException();
            tradeId = customerDao.exitTradeCount(currentRole.getUid(), salesId, product.getSkuName());

//            返回交易信息并更新交易备注
            CustomerServicePrinter.printTradeInfo(customerDao.selectTradeById(tradeId));
            waitThread.interrupt();
            Thread.sleep(150);
            while (true) {
                String msg = ProjectUtil.getLine("是否确认交易信息(y/n): ", checker);
                if (msg.equals("y")) break;
                if (msg.equals("n")) throw new SQLException(); // 回滚数据
            }
            conn.commit();
            String note = ProjectUtil.getLine("还有什么交易备注信息吗：", nonChecker);
            if (note != null) {
                int noteCount = customerDao.updateTradeNodeByTradeId(tradeId, note);
                if (noteCount != 1) throw new SQLException();
            }
        } catch (NotFindInfoException | InputFormatException | InterruptedException | NotEnoughStockException |
                 SQLSyntaxErrorException e) {
            Console.println(e.getMessage(), LogEffect.RED, LogEffect.BOLD);
            buy(menuContext);
        } catch (SQLException e) {
            if (ObjectUtil.isNotNull(conn)) {
                try {
                    conn.rollback();
                } catch (SQLException ex) {
                    Console.println(e.getMessage(), LogEffect.RED, LogEffect.BOLD);
                }
                buy(menuContext);
            }
        } catch (NotFindRelativeSalesException e) {
            Console.println(e.getMessage(), LogEffect.RED, LogEffect.BOLD);
            return Action.JUMP_TO_MENU("/customer");
        }
        return Action.JUMP_TO_MENU("/customer/product");
    }

    @Override
    public Action deleteAccount(MenuContext menuContext) {
        Connection conn = null;
        while (true) {
            String msg = ProjectUtil.getLine("是否确认注销，该操作不可回溯！(y/n): ", checker);
            if (msg.equals("y")) {
                try {
                    conn = ProjectUtil.getConnection();
                    Thread waitThread = IOUtil.waitForSelective(WaitForStatusConstant.DELETE);
                    Role currentRole = (Role) menuContext.getState().get("CurrentRole");
                    String uid = currentRole.getUid();
//                    删除关系
                    int relationCount = customerDao.deleteRelationByUid(uid);
//                    删除交易信息
                    customerDao.deleteTradeByClientUid(uid);
//                    删除与之有关的信息
                    customerDao.deleteMsgByUid(uid);
//                    删除角色信息
                    int roleCount = customerDao.deleteRoleByUid(uid);
//                    删除用户信息
                    int userCount = customerDao.deleteUserById(uid);
                    if (relationCount != 1 || roleCount != 1 || userCount != 1) throw new SQLException();
                    conn.commit();
                    waitThread.interrupt();
                    Thread.sleep(150);
                } catch (InterruptedException e) {
                    Console.println(e.getMessage(), LogEffect.RED, LogEffect.BOLD);
                    deleteAccount(menuContext);
                } catch (SQLException e) {
                    if (ObjectUtil.isNotNull(conn)) {
                        try {
                            conn.rollback();
                        } catch (SQLException ex) {
                            Console.println(e.getMessage(), LogEffect.RED, LogEffect.BOLD);
                        }
                        deleteAccount(menuContext);
                    }
                }
                return Action.JUMP_TO_MENU("/");  // 跳转到登陆页面
            }
            if (msg.equals("n")) return Action.JUMP_TO_MENU("/customer/user");
        }
    }

    @Override
    public Action updateUsnaPasw(MenuContext menuContext) {
        try {
            String username = ProjectUtil.getLine("请输入最新的用户名：", checker);
            String password = ProjectUtil.getLine("请输入最新的密码：", checker);
            String verifyPassword = ProjectUtil.getLine("再次确认密码：", checker);
            if (password.length() < 8) throw new SystemErrorException("密码长度大于8位！");
            if (!password.equals(verifyPassword)) throw new SystemErrorException("两次密码不一致！");
            Thread waitThread = IOUtil.waitForSelective(WaitForStatusConstant.UPDATE);
            Role currentRole = (Role) menuContext.getState().get("CurrentRole");
            int count = customerDao.updateRoleUsnaPaswByUid(currentRole.getUid(), username, password);
            if (count != 1) throw new SystemErrorException();
            waitThread.interrupt();
            Thread.sleep(150);
        } catch (SystemErrorException | InterruptedException e) {
            Console.println(e.getMessage(), LogEffect.RED, LogEffect.BOLD);
            updateUsnaPasw(menuContext);
        }
        return Action.JUMP_TO_MENU("/customer/user");
    }

    @Override
    public Action completeInfo(MenuContext menuContext) {
        Thread waitThread =null;
        try {
            Role currentRole = (Role) menuContext.getState().get("CurrentRole");
            User user = customerDao.selectUserById(currentRole.getUid());
            String newPhoneNumber = ProjectUtil.getLine("最新电话号码：", nonChecker);
            String newAnnualIncome = null;
            for (; ; ) {
                newAnnualIncome = ProjectUtil.getLine("最新年收入：", nonChecker); //bigdecimal
                if (NumberUtil.isInteger(newAnnualIncome) || ObjectUtil.isNull(newAnnualIncome)) break;
                else Console.println("请输入整数!", LogEffect.RED, LogEffect.BOLD);
            }
            String newIndustry = ProjectUtil.getLine("最新行业：", nonChecker);
            String newDescription = ProjectUtil.getLine("最新用户描述：", nonChecker);
            String newCountry = ProjectUtil.getLine("最新国家：", nonChecker);
            String newProvince = ProjectUtil.getLine("最新省份：", nonChecker);
            String newCity = ProjectUtil.getLine("最新市：", nonChecker);
            String newDistrict = ProjectUtil.getLine("最新区：", nonChecker);
            String newPostCode = ProjectUtil.getLine("最新邮政编码：", nonChecker);

            user.setPhoneNumber(ObjectUtil.isNotNull(newPhoneNumber) ? newPhoneNumber : user.getPhoneNumber());
            user.setAnnualIncome(ObjectUtil.isNotNull(newAnnualIncome) ? new BigDecimal(newAnnualIncome) : user.getAnnualIncome());
            user.setIndustry(ObjectUtil.isNotNull(newIndustry) ? newIndustry : user.getIndustry());
            user.setDescription(ObjectUtil.isNotNull(newDescription) ? newDescription : user.getDescription());
            user.setCountry(ObjectUtil.isNotNull(newCountry) ? newCountry : user.getCountry());
            user.setProvince(ObjectUtil.isNotNull(newProvince) ? newProvince : user.getProvince());
            user.setCity(ObjectUtil.isNotNull(newCity) ? newCity : user.getCity());
            user.setDistrict(ObjectUtil.isNotNull(newDistrict) ? newDistrict : user.getDistrict());
            user.setPostCode(ObjectUtil.isNotNull(newPostCode) ? newPostCode : user.getPostCode());

            waitThread=IOUtil.waitForSelective(WaitForStatusConstant.UPDATE);
            int count = customerDao.updateUser(user);
            if (count < 1) throw new SystemErrorException();
            waitThread.interrupt();
            Thread.sleep(150);
        } catch (SystemErrorException | InterruptedException e) {
            Console.println(e.getMessage(), LogEffect.RED, LogEffect.BOLD);
            waitThread.interrupt();
            try {
                Thread.sleep(150);
            } catch (InterruptedException ex) {
                throw new RuntimeException(ex);
            }
        }
        return Action.JUMP_TO_MENU("/customer/user");

    }

    @Override
    public Action showContract(MenuContext menuContext) {
        try {
            Role currentRole = (Role) menuContext.getState().get("CurrentRole");
            if (currentRole.getIsBelong() == BelongStatus.FALSE) throw new NonRelativeSalespersonException();
            List<Trade> tradeList = Optional.ofNullable(customerDao.selectAllConfirmDealTradeByClientId(currentRole.getUid())).orElse(new ArrayList<Trade>());
            if (tradeList.size() == 0) {
                if (customerDao.exitTradeCount(currentRole.getUid()) == 0)
                    Console.println("请耐心等待销售处理", LogEffect.YELLOW, LogEffect.BOLD);
                else Console.println("当前没有交易信息", LogEffect.YELLOW, LogEffect.BOLD);
                return Action.JUMP_TO_MENU("/customer/product");
            }

//              打印交易合同
            System.out.println("  |       合同id       |      成交产品         |  ");
            for (Trade trade : tradeList) {
                System.out.print("  |  " + trade.getTradeId() + "  ");
                System.out.println("  |  " + trade.getGoodsName() + "  |  ");
            }
            String tradeId = ProjectUtil.getLine("输入e退出，输入合同id查看详情: ", checker);
            if ("e".equals(tradeId)) return Action.JUMP_TO_MENU("/customer/product");

            Trade trade = Optional.ofNullable(customerDao.selectTradeById(tradeId)).orElseGet(() -> Trade.builder().build());
            CustomerServicePrinter.printContract(trade);
        } catch (NonRelativeSalespersonException e) {
            Console.println(e.getMessage(), LogEffect.RED, LogEffect.BOLD);
            return Action.JUMP_TO_MENU("/customer");
        }
        return Action.JUMP_TO_MENU("/customer/product");
    }

    @Override
    public Action showContractStatus(MenuContext menuContext) {
        try {
            Role currentRole = (Role) menuContext.getState().get("CurrentRole");
            Thread waitThread = IOUtil.waitForSelective(WaitForStatusConstant.SELECT);
            List<Trade> tradeList = Optional.ofNullable(customerDao.selectAllTradeByClientId(currentRole.getUid())).orElse(new ArrayList<>());
            waitThread.interrupt();
            Thread.sleep(150);
            if (tradeList.size() == 0) {
                Console.println("尚未有合同信息！", LogEffect.YELLOW, LogEffect.BOLD);
                return Action.JUMP_TO_MENU("/customer");
            }
            CustomerServicePrinter.printTradeStatus(tradeList);

        } catch (InterruptedException e) {
            Console.println(e.getMessage(), LogEffect.RED, LogEffect.BOLD);
            showContractStatus(menuContext);
        }
        return Action.JUMP_TO_MENU("/customer");
    }
}
